package com.hippo.database.aspect;

import cn.hutool.core.date.LocalDateTimeUtil;
import com.alibaba.fastjson.JSON;
import com.hippo.core.pojo.entity.SysRequestLog;
import com.hippo.core.pojo.vo.LoginUser;
import com.hippo.database.mapper.SysRequestLogMapper;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.net.InetAddress;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;


/**
 * @ClassName RequestLog
 * @Description TODO 接口日志
 * @Author tangxl
 * @create 2023-05-08 15:06
 **/
@Aspect
@Component
@Slf4j
@RequiredArgsConstructor
public class RequestLogAspect {

    private final SysRequestLogMapper requestLogMapper;
    private final RedisTemplate redisTemplate;


    /**
     * 获取所有controller包下的所有方法
     */
    @Pointcut("@annotation(org.springframework.web.bind.annotation.RequestMapping)" +
            "||@annotation(org.springframework.web.bind.annotation.GetMapping)" +
            "||@annotation(org.springframework.web.bind.annotation.PostMapping)" +
            "||@annotation(org.springframework.web.bind.annotation.PutMapping)" +
            "||@annotation(org.springframework.web.bind.annotation.DeleteMapping)" +
            "||@annotation(org.springframework.web.bind.annotation.PatchMapping)")
    public void requestLog(){}

    @Around("requestLog()")
    @Transactional(rollbackFor = Exception.class)
    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
        //开始时间
        long startTime = System.currentTimeMillis();
        // 获取request对象
         HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        // 获取token
        String token = request.getHeader("token");
        // 获取请求接口
        String uri = request.getRequestURI();
        // 获取请求参数
        Object[] args = joinPoint.getArgs();
        //过滤掉request和response类型的参数
        List<Object> requestArgs = Arrays.stream(args)
                .filter(arg -> (!(arg instanceof HttpServletRequest) && !(arg instanceof HttpServletResponse)))
                .collect(Collectors.toList());
        // 获取请求java方法名称
        String classMethod = joinPoint.getSignature().getName();
        String method = request.getMethod();
        // 获取请求类名
        String className = joinPoint.getTarget().getClass().getName();
        log.info("接口日志");
        log.info("请求接口：{}",uri);
        log.info("请求类名：{}",className);
        log.info("请求方法名：{}",classMethod);
        log.info("请求方法：{}",method);
        log.info("请求参数：{}",requestArgs);
        SysRequestLog requestLog = new SysRequestLog();
        requestLog.setDescription("接口日志");
        // 获取用户信息
        if(StringUtils.isNotEmpty(token)){
            LoginUser user = (LoginUser)redisTemplate.opsForValue().get(token);
            if(user != null){
                requestLog.setUserId(user.getId());
                requestLog.setUsername(user.getName());
            }
        }else {
            requestLog.setUserId(0);
            requestLog.setUsername("未登录");
        }
        // 开始时间
        requestLog.setStartTime(LocalDateTimeUtil.of(startTime));
        System.out.println("开始时间："+requestLog.getStartTime());
        // 执行方法
        Object result = joinPoint.proceed();
        // 结束时间
        long endTime = System.currentTimeMillis();
        requestLog.setSpendTime(startTime - endTime);
        // 获取当前服务器ip
        String serviceIp = InetAddress.getLocalHost().getHostAddress();
        // 获取当前服务器端口
        int servicePort = request.getLocalPort();
        String basePath = "http://"+serviceIp+":"+servicePort;
        requestLog.setBasePath(basePath);
        requestLog.setUri(uri);
        requestLog.setUrl(basePath+uri);
        requestLog.setMethod(request.getMethod());
        requestLog.setClassMethod(classMethod);
        requestLog.setIp(request.getRemoteAddr());
        requestLog.setResult(JSON.toJSONString(result));

//        requestLog.setRequestParameter(JSON.toJSONString(requestArgs));
        requestLogMapper.insert(requestLog);
        return result;
    }

}
